﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Speech.Synthesis;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
using Labthink.PCSoft.UniversalHost4.Instrument.Forms;
using Labthink.PCSoft.UniversalHost4.Model;
using Labthink.PCSoft.UniversalHost4.Model.User;
using Labthink.PCSoft.UniversalHost4.UserControls;
using Labthink.PCSoft.UniversalHost4.UserControls.MsgBox;
using Labthink.PCSoft.UniversalHost4.Utility;
using NLog;
using Report;
using SystemSettings;
using Labthink.PCSoft.UniversalHost4.DataAccess;
using Labthink.PCSoft.UniversalHost4.Model.Setting;
using Application = System.Windows.Application;
using Button = System.Windows.Controls.Button;
using ContextMenu = System.Windows.Controls.ContextMenu;
using FileInfo = System.IO.FileInfo;
using KeyEventArgs = System.Windows.Input.KeyEventArgs;
using MenuItem = System.Windows.Controls.MenuItem;
using MessageBox = System.Windows.MessageBox;

namespace Labthink.PCSoft.UniversalHost4
{
    public partial class MainWindow
    {
        private Logger _logger = LogManager.GetCurrentClassLogger();

        public TcpCommands.Instrument Instrument { get; set; }

        private readonly DispatcherTimer _autoLockScreenTimer;

        private readonly SpeechSynthesizer _speech = new SpeechSynthesizer();
        private NotifyManager _notify;
        private int _autoLockTime;

        public MainWindow()
        {
            InitializeComponent();
            DataContext = this;
            _autoLockScreenTimer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(2) };
            _autoLockScreenTimer.Tick += AutoLockScreenTimer_Tick;
            _autoLockScreenTimer.IsEnabled = true;
            _speech.Volume = 100;
            if (!Debugger.IsAttached)
            {
                WindowState = WindowState.Maximized;
            }
            else
            {
                WindowState = WindowState.Normal;

                //double height = SystemParameters.FullPrimaryScreenHeight;
                //double width = SystemParameters.FullPrimaryScreenWidth;

                //Width = 1024;
                //Height = 768;

                //Top = (height - Height) / 2;
                //Left = (width - Width) / 2;
            }
        }

        private void AutoLockScreenTimer_Tick(object sender, EventArgs e)
        {
            if (IndicatorLock.IsBusy == false && _autoLockTime > 0)
            {
                long ua = Win32Api.GetLastInputTime() / 1000;
                if (ua / 60.0 > _autoLockTime)
                {
                    _logger.Debug($"超过{ua}秒没有任何操作，锁定账户");
                    IndicatorLock.IsBusy = true;
                    _autoLockScreenTimer.IsEnabled = false;
                }
            }
        }

        private void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            if (!Debugger.IsAttached)
            {
                WindowState = WindowState.Maximized;
            }

            BtnInit.Visibility = Visibility.Collapsed;
            BtnSerialSet.Visibility = Visibility.Collapsed;
            _notify = NotifyManager.InstanceManager(this);

            _autoLockScreenTimer.Start();
            SetLanguageMenu();

            Instrument = InstrumentManager.GetDefault();
            Common.Instrument = Instrument;

            if (Common.UiSetting.TitleShowAppName)
            {
                Title = Common.BaseInfo.Name;
            }

            if (Common.UiSetting.TitleShowAppName && Common.UiSetting.TitleShowVersion)
            {
                Title = Common.BaseInfo.Name + $" ({Common.BaseInfo.Version})";
            }

            LblCurrentIns.Content = Title;
            if (Common.BaseInfo.Gmp)
            {
                Common.IsSign = Common.GmpInfo.Sign;
            }

            //    if (Instrument.CustomInfo != null)
            //    {
            //        var logo = string.Empty;
            //        if (!string.IsNullOrEmpty(Instrument.CustomInfo.CustLogo))
            //        {
            //            var file = AppDomain.CurrentDomain.BaseDirectory + Instrument.CustomInfo.CustLogo;
            //            if (File.Exists(file))
            //            {
            //                BinaryReader binReader = new BinaryReader(File.Open(file, FileMode.Open));
            //                var fileInfo = new FileInfo(file);
            //                byte[] bytes = binReader.ReadBytes((int)fileInfo.Length);
            //                binReader.Close();
            //                logo = Convert.ToBase64String(bytes);
            //            }
            //        }

            //        rm.SetNameAndLogo(Instrument.CustomInfo.CustName, logo);
            //        mm.SetNameAndLogo(Instrument.CustomInfo.CustName, logo);
            //    }

            Indicator.IsBusy = false;

            var login = States.Instance.LoginControl;
            Common.LoginSuccess += OnLoginLoginSuccess;
            Main.Content = login;
            _logger.Debug("MainWindow_Loaded");
        }

        private void SetLanguageMenu()
        {
            BtnChangeLanguage.ContextMenu?.Items.Clear();

            foreach (Language lan in LanguageManager.Languages)
            {
                string name = lan.DisplayName;
                string code = lan.Code;

                var mi = new MenuItem
                {
                    Header = name,
                    IsChecked = (code == SystemInfo.GetCurrentLocale())
                };

                mi.Click += OnMenuItemClick;

                void OnMenuItemClick(object o, RoutedEventArgs routedEventArgs)
                {
                    var menuItem = o as MenuItem;
                    if (menuItem?.Parent is ContextMenu menu)
                    {
                        foreach (MenuItem mit in menu.Items.Cast<MenuItem>())
                        {
                            if (!Equals(mit, menuItem))
                            {
                                mit.IsChecked = false;
                            }
                        }
                    }

                    Common.UserSettings.Locale = code;
                    if (menuItem != null) menuItem.IsChecked = true;
                    Common.UserSettings.Save();
                    _notify.ShowSuccess(LanguageManager.GetLanguageValue("RestartToTakeEffect"));
                }

                BtnChangeLanguage.ContextMenu?.Items.Add(mi);
            }
        }

        private void _createUserMenu(UserInfo user)
        {
            TxtUser.ContextMenu?.Items.Clear();
            var mi = new MenuItem
            {
                Icon = new TextBlock
                {
                    FontSize = 20,
                    Text = "\uf13e",
                    FontFamily = Resources["FontAwesome"] as FontFamily
                },
                Header = new TextBlock
                {
                    FontSize = 20,
                    Text = LanguageManager.GetLanguageValue("LockUser"),
                    VerticalAlignment = VerticalAlignment.Center
                }
            };

            mi.Click += Locked_OnClick;
            TxtUser.ContextMenu?.Items.Add(mi);
            if (user.Role > 1)
            {
                mi = new MenuItem
                {
                    Icon = new TextBlock
                    {
                        FontSize = 20,
                        Text = "\uf0f0",
                        FontFamily = Resources["FontAwesome"] as FontFamily
                    },

                    Header = new TextBlock
                    {
                        FontSize = 20,
                        Text = LanguageManager.GetLanguageValue("ChangePasswordWindowTitle"),
                        VerticalAlignment = VerticalAlignment.Center
                    }
                };

                mi.Click += ChangePwd_Click;
                TxtUser.ContextMenu?.Items.Add(mi);
            }

            mi = new MenuItem
            {
                Icon = new TextBlock
                {
                    FontSize = 20,
                    Text = "\uf08b",
                    FontFamily = Resources["FontAwesome"] as FontFamily
                },
                Header = new TextBlock
                {
                    FontSize = 20,
                    Text = LanguageManager.GetLanguageValue("Logout"),
                    VerticalAlignment = VerticalAlignment.Center
                }
            };

            mi.Click += Logout_Click;
            TxtUser.ContextMenu?.Items.Add(mi);
        }

        private void OnLoginLoginSuccess(object s, UserAndPermission user)
        {
            _logger.Debug("OnLoginLoginSuccess");
            Common.IsFromLogout = false;
            GridLeft.Visibility = Visibility.Collapsed;
            SbiMenu.Background = null;
            GridOuter.ColumnDefinitions[0].Width = new GridLength(0);

            var main = States.Instance.Main;
            Main.Content = main;

            //获取试验报告模板
            List<ReportConfig> cfgs = ReportConfigManager.GetConfigs();

            //单腔
            var manager = ReportManager2.Create();
            manager.Permissions = Common.Permissions;
            manager.User = Common.CurrentUser;
            manager.GetConfigs(cfgs);

            //初始化用户信息
            _createLoginInfo(user.Info);
            _autoLockTime = Common.SafeInfo.AccountLockTime;
            _logger.Debug("MainWindow OnLoginLoginSuccess end");

            BtnLogo_OnClick(null, null);
            if (Common.CurrentUser.LoginName == "Administrator")
            {
                //BtnInit.Visibility = Visibility.Visible;
                //BtnSerialSet.Visibility = Visibility.Visible;
            }
            if (Common.Permissions.All(p => p.Code != "Per_ComSetting".Clear()))
            {
                BtnSerialSet.Visibility = Visibility.Collapsed;
            }
            else
            {
                BtnSerialSet.Visibility = Visibility.Visible;
            }
            if (Common.Permissions.All(p => p.Code != "Per_OperationLog".Clear()))
            {
                BtnInit.Visibility = Visibility.Collapsed;
            }
            else
            {
                BtnInit.Visibility = Visibility.Visible;
            }
        }

        private void OnLogout(object sender1, EventArgs e1)
        {
            _autoLockTime = 0;
            Common.IsFromLogout = true;

            // 返回登录界面
            Dispatcher?.Invoke(() =>
            {
                BtnInit.Visibility = Visibility.Collapsed;
                _autoLockScreenTimer.IsEnabled = false;
                var login = States.Instance.LoginControl;
                login.TxtUserId.Text = "";
                login.TxtPassword.Password = "";
                Main.Content = login;
                TxtUser.Visibility = Visibility.Collapsed;
                TxtUser.ContextMenu?.Items.Clear();
                BtnChangeLanguage.Visibility = Visibility.Visible;
                BtnSerialSet.Visibility = Visibility.Collapsed;
                ImgLogo.Visibility = Visibility.Collapsed;
                LogRepository.AddLog(LanguageManager.GetLanguageValue("OP-UserLogout"), "Manage");
            });
        }

        private void _createLoginInfo(UserInfo user)
        {
            BitmapImage bmp = null;
            if (Common.CustomInfo != null &&
                !string.IsNullOrEmpty(Common.CustomInfo.CustLogo))
            {
                var file = AppDomain.CurrentDomain.BaseDirectory +
                           Common.CustomInfo.CustLogo;
                var binReader = new BinaryReader(File.Open(file, FileMode.Open));
                var fileInfo = new FileInfo(file);
                byte[] bytes = binReader.ReadBytes((int)fileInfo.Length);
                binReader.Close();
                bmp = new BitmapImage();
                bmp.BeginInit();
                bmp.StreamSource = new MemoryStream(bytes);
                bmp.EndInit();
            }

            Dispatcher?.Invoke(() =>
            {
                TxtUser.Visibility = Visibility.Visible;
                TxtUser.Text = user.LoginName;

                BtnChangeLanguage.Visibility = Visibility.Visible;
                GridLeft.Visibility = Visibility.Collapsed;
                if (bmp != null) ImgLogo.Source = bmp;
                ImgLogo.Visibility = Visibility.Visible;
                SbiMenu.Background = null;
                GridOuter.ColumnDefinitions[0].Width = new GridLength(0);
                _createUserMenu(user);
            });
        }

        protected override void OnClosed(EventArgs e)
        {
            base.OnClosed(e);
            //sc?.Close();
            Application.Current.Shutdown();
        }

        private void BtnLogo_OnClick(object sender, RoutedEventArgs e)
        {
            switch (GridLeft.Visibility)
            {
                case Visibility.Collapsed:
                    GridLeft.Visibility = Visibility.Visible;
                    SbiMenu.Background = new SolidColorBrush(Color.FromArgb(0xff, 0xfc, 0xc7, 0x00));
                    GridOuter.ColumnDefinitions[0].Width = new GridLength(60);
                    break;

                case Visibility.Visible:
                    GridLeft.Visibility = Visibility.Collapsed;
                    SbiMenu.Background = null;
                    GridOuter.ColumnDefinitions[0].Width = new GridLength(0);
                    break;
            }
        }

        private void BtnChangeLanguage_OnClick(object sender, RoutedEventArgs e)
        {
            var btn = sender as Button;
            if (btn?.ContextMenu != null)
            {
                btn.ContextMenu.IsEnabled = true;
                btn.ContextMenu.PlacementTarget = btn;
                btn.ContextMenu.Placement = System.Windows.Controls.Primitives.PlacementMode.Bottom;
                btn.ContextMenu.IsOpen = true;
            }
        }

        private void main_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Escape)
            {
                if (this.IsFullscreen())
                {
                    BtoBar.Visibility = Visibility.Collapsed;
                    this.ExitFullscreen();
                }
            }
        }

        private void main_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            if (Debugger.IsAttached)
            {
                return;
            }

            Top = 0;
            Left = 0;
            Height = SystemParameters.FullPrimaryScreenHeight + 25;
            Width = SystemParameters.FullPrimaryScreenWidth;
        }

        private void MainWindow_OnClosing(object sender, CancelEventArgs e)
        {
            if (States.Instance.SerialPort != null && States.Instance.SerialPort.IsOpen)
            {
                States.Instance.SerialPort.ClosePort();
            }

            foreach (var p in Process.GetProcesses())
            {
                if (p.ProcessName == "Keyboard" || p.ProcessName == "Numpad") p.Kill();
            }

            if (Common.TestStatus == TestStatus.Testing)
            {
                MyMessageBox.Show(this, LanguageManager.GetLanguageValue("TestOngoingOperationNotAllowed"),
                    MyMessageBoxButton.Ok, MyMessageBoxImage.Warning);
            }

            //if (Common.TestStatus == TestStatus.End)
            //{
            //    MyMessageBox.Show(this, LanguageManager.GetLanguageValue("SaveTestFirst"),
            //        MyMessageBoxButton.Ok, MyMessageBoxImage.Warning);
            //}
        }

        private void BtnMin_OnClick(object sender, RoutedEventArgs e)
        {
            WindowState = WindowState.Minimized;
        }
        private void BtnRestore_OnClick(object sender, RoutedEventArgs e)
        {
            if (WindowState == WindowState.Maximized)
            {
                WindowState = WindowState.Normal;
            }
            else
            {
                WindowState = WindowState.Maximized;
            }
        }

        private void BtnClose_OnClick(object sender, RoutedEventArgs e)
        {
            if (Common.TestStatus == TestStatus.Testing)
            {
                MyMessageBox.Show(this, LanguageManager.GetLanguageValue("TestOngoingOperationNotAllowed"),
                    MyMessageBoxButton.Ok, MyMessageBoxImage.Warning);
                return;
            }

            //if (Common.TestStatus == TestStatus.End)
            //{
            //    MyMessageBox.Show(this, LanguageManager.GetLanguageValue("SaveTestFirst"),
            //        MyMessageBoxButton.Ok, MyMessageBoxImage.Warning);
            //    return;
            //}

            var result = MyMessageBox.Show(this, LanguageManager.GetLanguageValue("ExitConfirm"),
                MyMessageBoxButton.OkCancel, MyMessageBoxImage.Warning);

            if (result == MyMessageBoxResult.Ok)
            {
                if (States.Instance.SerialPort != null && States.Instance.SerialPort.IsOpen)
                {
                    States.Instance.SerialPort.ClosePort();
                }

                foreach (var p in Process.GetProcesses())
                {
                    if (p.ProcessName == "Keyboard" || p.ProcessName == "Numpad") p.Kill();
                }
                Application.Current.Shutdown();
            }
        }

        private void BtnHelp_OnClick(object sender, RoutedEventArgs e)
        {
            var ex = "pdf";
            string file = $"Help.{LanguageManager.CurrentLanguage}.{ex}";
            string help = Path.Combine(Common.AppPath, file);
            if (!File.Exists(help))
            {
                ex = "docx";
                file = $"Help.{LanguageManager.CurrentLanguage}.{ex}";
                help = Path.Combine(Common.AppPath, file);
            }

            if (File.Exists(help))
            {
                Process.Start(help);
            }
        }

        private void BtnLicense_OnClick(object sender, RoutedEventArgs e)
        {
            var license = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "licenses.ini");
            if (File.Exists(license))
            {
                Process.Start(license);
            }
        }

        private void BtnAbout_OnClick(object sender, RoutedEventArgs e)
        {
            var about = new About();
            about.ShowDialog(this);
        }

        private void Locked_OnClick(object sender, RoutedEventArgs e)
        {
            IndicatorLock.IsBusy = true;
            _autoLockScreenTimer.IsEnabled = false;
        }

        private void ChangePwd_Click(object sender, RoutedEventArgs e)
        {
            var frm = new ChangePassword();
            frm.ShowDialog(this);
        }

        private void Logout_Click(object sender, RoutedEventArgs e)
        {
            if (Common.TestStatus == TestStatus.Testing)
            {
                MyMessageBox.Show(this, LanguageManager.GetLanguageValue("TestOngoingOperationNotAllowed"),
                    MyMessageBoxButton.Ok, MyMessageBoxImage.Warning);

                return;
            }

            //if (Common.TestStatus == TestStatus.End)
            //{
            //    MyMessageBox.Show(this, LanguageManager.GetLanguageValue("SaveTestFirst"),
            //        MyMessageBoxButton.Ok, MyMessageBoxImage.Warning);
            //    return;
            //}

            var result = MyMessageBox.Show(this, LanguageManager.GetLanguageValue("LogoutConfirm"),
                MyMessageBoxButton.OkCancel, MyMessageBoxImage.Warning);
            if (result == MyMessageBoxResult.Ok)
                OnLogout(null, null);
        }

        private void BtnUnlock_OnClick(object sender, RoutedEventArgs e)
        {
            var g = (sender as Button)?.Parent as Grid;
            var txt = g.FindName("TxtUserId") as UcTextBox;
            var pwd = g.FindName("TxtPassword") as UcPassword;
            if (string.IsNullOrEmpty(pwd.Pwd.Password) || string.IsNullOrEmpty(txt.Value)) return;
            if (txt.Value != Common.CurrentUser.LoginName)
            {
                MessageBox.Show(LanguageManager.GetLanguageValue("UserIdMustEqualsCurrent"));
                return;
            }

            string hash = PasswordHash.HashPassword(pwd.Pwd.Password, Common.CurrentUser.Salt);
            if (hash != Common.CurrentUser.Password)
            {
                MessageBox.Show(LanguageManager.GetLanguageValue("AuthFailed"));
                return;
            }

            txt.Value = "";
            pwd.Pwd.Password = "";
            IndicatorLock.IsBusy = false;
            _autoLockScreenTimer.IsEnabled = true;
        }

        public T FindVisualChildren<T>(DependencyObject obj, string childName) where T : DependencyObject
        {
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
            {
                DependencyObject child = VisualTreeHelper.GetChild(obj, i);
                if (child is T dependencyObject && dependencyObject.GetValue(NameProperty).ToString() == childName)
                {
                    return dependencyObject;
                }

                T childOfChild = FindVisualChildren<T>(child, childName);
                if (childOfChild != null)
                {
                    return childOfChild;
                }
            }

            return null;
        }

        private void TxtUser_OnMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            Menu.IsOpen = true;
        }

        private void BtnInit_OnClick(object sender, RoutedEventArgs e)
        {
            var frm = new FrmOpLog();
            frm.ShowDialog(Application.Current.MainWindow);

        }

        private void BtnSerialSet_OnClick(object sender, RoutedEventArgs e)
        {
            var frm = new FrmSerialSet();
            frm.ShowDialog(Application.Current.MainWindow);
        }

    }
}
